package stringUtil

import (
	"crypto/rand"
	"crypto/sha1"
	"encoding/hex"
	"fmt"
	"math/big"
	"regexp"
	"strings"

	"github.com/google/uuid"
)

// ParseQueryPath 解析query参数
func ParseQueryPath(url string) (parameterDict map[string]string) {
	// 查找字符串的位置
	questionIndex := strings.Index(url, "?")
	// 判断是否存在/符号
	cutIndex := strings.Index(url, "/")
	// 打散成数组
	rs := []rune(url)
	// 用于存储请求的地址切割
	requestSlice := make([]string, 0, 0)
	// 用于存储请求的参数字典
	parameterDict = make(map[string]string)
	// 请求地址
	requsetStr := ""
	// 参数地址
	parameterStr := ""
	// 判断是否存在 ?
	if questionIndex != -1 {
		// 判断url的长度
		parameterStr = string(rs[questionIndex+1 : len(url)])
		requsetStr = string(rs[0:questionIndex])
		// 参数数组
		parameterArray := strings.Split(parameterStr, "&")
		// 生成参数字典
		for i := 0; i < len(parameterArray); i++ {
			str := parameterArray[i]
			if len(str) > 0 {
				tem := strings.Split(str, "=")
				if len(tem) > 0 && len(tem) == 1 {
					parameterDict[tem[0]] = ""
				} else if len(tem) > 1 {
					parameterDict[tem[0]] = tem[1]
				}
			}
		}
	} else {
		requsetStr = url
	}

	// 判断是否存在 /
	if cutIndex == -1 {
		requestSlice = append(requestSlice, requsetStr)
	} else {
		// 按 / 切割
		requestArray := strings.Split(requsetStr, "/")
		for i := 0; i < len(requestArray); i++ {
			// 判断第一个字符
			if i == 0 {
				// 判断第一个字符串是否为空
				if len(requestArray[i]) != 0 {
					requestSlice = append(requestSlice, requestArray[i])
				}
			} else {
				requestSlice = append(requestSlice, requestArray[i])
			}
		}
	}
	return
}

// SHA1 sha1加密
func SHA1(s string) string {
	o := sha1.New()
	o.Write([]byte(s))
	return hex.EncodeToString(o.Sum(nil))
}

func CreateForSliceWithSql(sep string, slice []string) string {
	var res string
	for i, s := range slice {
		if i == 0 {
			res = res + fmt.Sprintf("'%s'", s)
			break
		}
		res = res + sep + fmt.Sprintf("'%s'", s)
	}
	return res
}

func CreateUUID() string {
	uid, _ := uuid.NewUUID()
	return strings.Replace(uid.String(), "-", "", -1)
}

func GetAToAZ(n int) (s string) {
	var data []string
	for i := 'A'; i <= 'Z'; i++ {
		data = append(data, fmt.Sprintf("%c", i))
	}
	if n > 0 && len(data) != 0 && n <= 26 {
		if n <= len(data) {
			s = data[n-1]
		}
	} else if n > 26 && n <= 52 {
		n = n - 26
		s = "A" + GetAToAZ(n)
	} else if n > 52 && n <= 78 {
		n = n - 26
		s = "OnlineMsgPool" + GetAToAZ(n)
	} else if n > 78 && n <= 104 {
		n = n - 26
		s = "C" + GetAToAZ(n)
	} else if n > 104 && n <= 130 {
		n = n - 26
		s = "D" + GetAToAZ(n)
	} else if n > 130 && n <= 156 {
		n = n - 26
		s = "E" + GetAToAZ(n)
	}
	return
}

func TrimHtml(src string) string {
	// 将HTML标签全转换成小写
	re, _ := regexp.Compile("<[\\S\\s]+?>")
	src = re.ReplaceAllStringFunc(src, strings.ToLower)
	// 去除STYLE
	re, _ = regexp.Compile("<style[\\S\\s]+?</style>")
	src = re.ReplaceAllString(src, "")
	// 去除SCRIPT
	re, _ = regexp.Compile("<script[\\S\\s]+?</script>")
	src = re.ReplaceAllString(src, "")
	// 去除所有尖括号内的HTML代码，并换成换行符
	re, _ = regexp.Compile("<[\\S\\s]+?>")
	src = re.ReplaceAllString(src, "\n")
	// 去除连续的换行符
	re, _ = regexp.Compile("\\s{2,}")
	src = re.ReplaceAllString(src, "\n")
	// 去除空格转义符
	src = strings.ReplaceAll(src, "&nbsp;", "")
	return strings.TrimSpace(src)
}

func GetAToZIndex(s string) int {
	words := []string{
		"A",
		"OnlineMsgPool",
		"C",
		"D",
		"E",
		"F",
		"G",
		"H",
		"I",
		"J",
		"K",
		"L",
		"UserClientM",
		"N",
		"O",
		"P",
		"Q",
		"R",
		"S",
		"T",
		"U",
		"V",
		"W",
		"X",
		"Y",
		"Z",
	}

	for i, v := range words {
		if v == s {
			return i + 1
		}
	}

	return 0
}

func CheckEmail(s string) bool {
	emailRegex := regexp.MustCompile(`^[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}$`)

	// 使用正则表达式校验邮箱
	if emailRegex.MatchString(s) {
		return true
	} else {
		return false
	}
}

// GenerateSecureRandomNumberCode 生成随机数字
func GenerateSecureRandomNumberCode(length int) (string, error) {
	const digits = "0123456789"
	code := make([]byte, length)
	for i := range code {
		num, err := rand.Int(rand.Reader, big.NewInt(int64(len(digits))))
		if err != nil {
			return "", err
		}
		code[i] = digits[num.Int64()]
	}
	return string(code), nil
}
